#include "packetparser.h"
#include "sbconstants.h"

#include <iostream>
#include "logmanager.h"
#include <sstream>

using namespace std;

PacketParser::PacketParser()
{
	numPacketsReceived = 0;
	lastNumPacketsReceived = 0;
	avgNumPackets = 0;
}

PacketParser::~PacketParser()
{
}

static sf::Uint8 lastPacketType = 255;
void PacketParser::HandlePacket(sf::IPAddress sender, unsigned short port, sf::Packet& packet)
{
	if (packet.GetDataSize() < 4)
	{
		std::stringstream ss;
		ss << "Packet to small: " << PacketToString(packet);
		LogManager::Log("packetparser", ss.str());
		return;
	}

	// Extract client id from the first 24 bits.
	sf::Uint32 clientID = ExtractIDFromPacket(packet);
	//std::cout << " sender: " << clientID << std::endl;

	++numPacketsReceived;

	// Handle all data in packet
	while ( !packet.EndOfPacket() )
	{
		sf::Uint8 type;
		packet >> type;
		sf::Uint8 group = type;

		switch (group)
		{
			case MESSAGE::TYPE::ADMIN:
				HandleAdminPacket(sender, port, clientID, packet);
				//LogManager::Log("packetparser", "HandleAdminPacket");
				break;

			case MESSAGE::TYPE::CONNECT:
				HandleConnectionPacket(sender, port, clientID, packet);
				//LogManager::Log("packetparser", "HandleConnectionPacket");
				break;

			case MESSAGE::TYPE::WORLD_UPDATE:
				HandleWorldUpdatePacket(sender, port, clientID, packet);
				//LogManager::Log("packetparser", "HandleWorldUpdatePacket");
				break;

			default:
			{
				stringstream ss;
				ss << "Error handling packet. No delegate picked up packet (recieving spam?) "
					<< " sender: " << sender
					<< " Port: " << port
					<< " Type: " << (int)type
					<< " LastType: " << (int)lastPacketType
					<< " Data: " << PacketToString(packet);
				LogManager::Log("packetparser", ss.str());
			}
				break;
		}
		lastPacketType = type;
	}
}

sf::Uint32 PacketParser::ExtractIDFromPacket(sf::Packet& packet)
{
	sf::Uint32 id = 0x00000000;

	sf::Uint8 temp;
	for (int i=0;i<3;i++)
	{
		packet >> temp;
		id |= temp;
		if ( i != 2 )
			id = (id << 4);
	}

	return id;
}

sf::Packet PacketParser::CreatePacketHeader(
	sf::Uint32 id,
	sf::Uint8 type)
{
	sf::Packet p;
	p 	<< (sf::Uint8)(id >> 8)
		<< (sf::Uint8)(id >> 4)
		<< (sf::Uint8)(id >> 0)
		<< type;
	return p;
}

std::string PacketParser::PacketToString(sf::Packet packet)
{
	stringstream ss;
	while (!packet.EndOfPacket())
	{
		sf::Uint8 x;
		packet >> x;
		ss << " | " << std::dec << (int)x;
	}
	return ss.str();
}
